package myJs.user

import myJs.Tool
import myJs.Utils._
import myJs.myPkg.Implicits._
import myJs.myPkg._
import myJs.myPkg.bootstrap.Bootstrap.default._
import myJs.myPkg.jquery._
import org.scalajs.dom.ext.Ajax
import org.scalajs.dom.raw.HTMLFormElement
import org.scalajs.dom.{FormData, _}
import scalatags.Text.TypedTag
import scalatags.Text.all._
import shared.VarTool

import scala.scalajs.js
import scala.scalajs.js.JSON
import scala.scalajs.js.annotation.{JSExport, JSExportTopLevel}
import scala.concurrent.ExecutionContext.Implicits.global
import scala.scalajs.js.JSConverters._
import myJs.implicits.Implicits._


/**
 * Created by Administrator on 2020/1/17
 */
@JSExportTopLevel("PfamAnno")
object PfamAnno {

  val kind = VarTool.pfamStr

  @JSExport("init")
  def init = {
    $("#missionTable").bootstrapTable()
    refreshTable()

    bootStrapValidator
    refreshMissionName

    updateMissionSocket

  }

  def showResult(id: String) = {
    val index = layer.load(1, Tool.layerOptions.shade(js.Array("0.1", "#fff")))
    val url = g.jsRoutes.controllers.GenomeController.pfamResult().url.toString
    Ajax.get(url = s"${url}?missionId=${id}").map { xhr =>
      val data = JSON.parse(xhr.responseText).asInstanceOf[js.Any]
      layer.close(index)
      refreshContent(data)
      $("#result").show()
      val target_top = $("#missionResult").offset().top
      jQuery("html,body").animate(js.Dictionary("scrollTop" -> target_top), JQueryAnimationSettings.duration(800))
    }
  }

  @JSExport("operateFmt")
  def operateFmt: js.Function = {
    (v: js.Any, row: js.Dictionary[js.Any]) =>
      val resetStr = a(
        title := "重置",
        onclick := s"UserManage.resetShow('" + row("id") + "')",
        cursor.pointer,
        span(
          em(cls := "fa fa-repeat")
        )
      )
      val deleteStr = a(
        title := "删除",
        cursor.pointer,
        onclick := s"genome.deleteMission('" + row("id") + "')",
        target := "_blank",
        span(
          em(cls := "fa fa-close")
        )
      )
      val downloadUrl = g.jsRoutes.controllers.GenomeController.downloadResult().url.toString
      val downloadStr = a(title := "下载结果", href := s"${downloadUrl}?missionId=${row("id")}", cursor.pointer,
        span(em(cls := "fa fa-download"))
      )
      val resultStr = a(
        title := "查看结果",
        cursor.pointer,
        onclick := s"PfamAnno.showResultBefore('" + row("id") + "','" + row("missionName") + "')",
        target := "_blank",
        span(
          em(cls := "fa fa-eye")
        )
      )
      val viewStr = a(title := "日志", onclick := s"genome.viewLog('${row("id")}')", cursor.pointer,
        span(em(cls := "fa fa-file-text"))
      )
      val state1 = if (List("success").contains(row("state"))) {
        List(downloadStr, resultStr)
      } else List[TypedTag[String]]()
      val state2 = if (!List("running").contains(row("state"))) {
        List(viewStr)
      } else List[TypedTag[String]]()
      val rs = state1 ::: state2 ::: List(deleteStr)
      rs.mkString("&nbsp;")
  }

  @JSExport("showResultBefore")
  def showResultBefore(id: String, missionName: String) = {
    $("#missionName").text(missionName)
    $("#missionId").`val`(id)
    showResult(id)
  }

  def initTable(columnNames: js.Array[String]) = {
    val checkboxHtml = columnNames.map { v =>
      label(marginRight := 15,
        input(`type` := "checkbox", checked := "checked", value := s"${v}", onclick := s"Utils.setColumns('${v}')", v)
      )
    }.mkString("")
    $("#checkbox").html(checkboxHtml)
    val columns = columnNames.map { columnName =>
      val title = columnName match {
        case _ => columnName
      }
      ColumnOptions.field(columnName).title(title).sortable(true)
    }
    val exportOptions = ExportOptions.csvSeparator("\t").fileName("pfam.anno.txt")
    val options = TableOptions.columns(columns).exportOptions(exportOptions).
      exportHiddenColumns(true)
    $("#table").bootstrapTable(options)
    columnNames.foreach { x =>
      $("#table").bootstrapTable("hideColumn", x)
      $(s"input:checkbox[value='${x}']").attr("checked", false)
    }
    val showColumns = columnNames.take(9)
    showColumns.foreach { x =>
      $("#table").bootstrapTable("showColumn", x)
      $(s"input:checkbox[value='${x}']").attr("checked", true)
    }
  }

  def refreshContent(data: js.Any) = {
    val rs = data.asInstanceOf[js.Array[js.Dictionary[String]]]
    val columnNames = rs.head.keys.toJSArray
    val tableId = "table"
    val tableHtml = $(s"#${tableId}").html().trim
    if (tableHtml.isEmpty) {
      initTable(columnNames)
    }
    $(s"#${tableId}").bootstrapTable("load", rs)
  }


  def updateMissionSocket = {
    val url = g.jsRoutes.controllers.GenomeController.updateMissionSocket(kind).url.toString
    val wsUri = s"ws://${window.location.host}${url}"
    webSocket(wsUri)
  }

  def webSocket(wsUri: String) = {
    val websocket = new WebSocket(wsUri)
    websocket.onopen = (evt) =>
      websocket.send(JSON.stringify(js.Dictionary("info" -> "start")))
    websocket.onclose = (evt) =>
      println(s"ERROR:${evt.code},${evt.reason},${evt.wasClean}")
    websocket.onmessage = (evt) => {
      val message = evt.data
      val data = JSON.parse(message.toString).asInstanceOf[js.Dictionary[String]]
      $("#missionTable").bootstrapTable("load", data)
    }
    websocket.onerror = (evt) => {
      updateByHand
      println(s"ERROR:${evt.toString}")
    }
  }

  def updateByHand = {
    js.timers.setInterval(3000) {
      refreshTable()
    }
  }

  def refreshTable(f: () => js.Any = () => ()) = {
    val url = g.jsRoutes.controllers.GenomeController.getAllMission().url.toString
    val ajaxSettings = JQueryAjaxSettings.url(s"${url}?kind=${kind}").contentType("application/json").
      `type`("get").success { (data: js.Any, status: String, e: JQueryXHR) =>
      $("#missionTable").bootstrapTable("load", data)
      f()
    }
    $.ajax(ajaxSettings)

  }

  @JSExport("myRun")
  def myRun = {
    val bv = jQuery("#form").data("bootstrapValidator")
    bv.validate()
    val valid = bv.isValid().asInstanceOf[Boolean]
    if (valid) {
      val formData = new FormData(document.getElementById("form").asInstanceOf[HTMLFormElement])
      $(":disabled").attr("disabled", false)
      val element = div(id := "content",
        span(id := "info", "正在运行",
          span(id := "progress", "。。。")), " ",
        img(src := "/assets/images/running2.gif", cls := "runningImage", width := 30, height := 20)
      ).render
      val layerOptions = LayerOptions.title(Tool.zhInfo).closeBtn(0).skin("layui-layer-molv").btn(js.Array())
      val index = layer.alert(element, layerOptions)
      val url = g.jsRoutes.controllers.GenomeController.pfamAnno().url.toString
      val xhr = new XMLHttpRequest
      xhr.open("post", url)
      xhr.upload.onprogress = progressHandlingFunction
      xhr.onreadystatechange = (e) => {
        if (xhr.readyState == XMLHttpRequest.DONE) {
          val data = xhr.response
          val rs = JSON.parse(data.toString).asInstanceOf[js.Dictionary[js.Any]]
          layer.close(index)
          refreshMissionName
          val valid = rs("valid").asInstanceOf[Boolean]
          if (valid) {
            refreshTable()
          } else {
            g.swal("Error", rs.myGet("message"), "error")
            $("#result").hide()
          }
        }
      }
      xhr.send(formData)
    }
  }

  def refreshMissionName = {
    $("input[name='missionName']").`val`(Genome.getCurrentTime)
    $("#form").bootstrapValidator("revalidateField", "missionName")
  }

  def bootStrapValidator = {
    val url = g.jsRoutes.controllers.GenomeController.missionNameCheck().url.toString
    val maxNumber = Double.MaxValue
    val dict = js.Dictionary(
      "feedbackIcons" -> js.Dictionary(
        "valid" -> "glyphicon glyphicon-ok",
        "invalid" -> "glyphicon glyphicon-remove",
        "validating" -> "glyphicon glyphicon-refresh",
      ),
      "fields" -> js.Dictionary(
        "queryText" -> js.Dictionary(
          "validators" -> js.Dictionary(
            "notEmpty" -> js.Dictionary(
              "message" -> "Query text不能为空！"
            )
          )
        ),
        "file" -> js.Dictionary(
          "validators" -> js.Dictionary(
            "notEmpty" -> js.Dictionary(
              "message" -> "Query fasta file不能为空！"
            ),
            "file" -> js.Dictionary(
              "extension" -> "fa,fasta",
              "message" -> "Query fasta file必须为fasta文件！",
            ),
          )
        ),
        "missionName" -> js.Dictionary(
          "validators" -> js.Dictionary(
            "notEmpty" -> js.Dictionary(
              "message" -> "任务名不能为空！"
            ),
            "remote" -> js.Dictionary(
              "message" -> "任务名已存在！",
              "url" -> url,
              "delay" -> 1000,
              "type" -> "POST",
              "data" -> js.Dictionary(
                "missionName" -> $("input[name='missionName']").`val`(),
                "kind" -> kind
              )
            ),
          )
        ),
        "seqCutoff" -> js.Dictionary(
          "validators" -> js.Dictionary(
            "notEmpty" -> js.Dictionary(
              "message" -> "Evalue sequence cutoff不能为空！"
            ),
            "numeric" -> js.Dictionary(
              "message" -> "Evalue sequence cutoff必须是数字！"
            ),
            "between" -> js.Dictionary(
              "min" -> 0,
              "max" -> maxNumber,
              "message" -> "Evalue sequence cutoff必须大于等于0！"
            ),
          )
        ),
        "domainCutoff" -> js.Dictionary(
          "validators" -> js.Dictionary(
            "notEmpty" -> js.Dictionary(
              "message" -> "Evalue domain cutoff不能为空！"
            ),
            "numeric" -> js.Dictionary(
              "message" -> "Evalue domain cutoff必须是数字！"
            ),
            "between" -> js.Dictionary(
              "min" -> 0,
              "max" -> maxNumber,
              "message" -> "Evalue domain cutoff必须大于等于0！"
            ),
          )
        ),
      )
    )
    g.$("#form").bootstrapValidator(dict)
  }


}
